#include <stdio.h>
#include "api.h"
#include "sdl.h"
#include "sas.h"
//#include "usb.h"
//#include "android/log.h"

#define LOG_TAG "LOADER"
#define SM_Printf(...) //__android_log_print(ANDROID_LOG_INFO  , LOG_TAG, __VA_ARGS__)

#define IRDETO_LOADER 0

int s_dwDeviceId;
static int s_dwLoaderType;
static const unsigned char s_abMixtermStart[4] = {STX, CMD_MIXTERM_START, CMD_DATA_MIXTERM_START, ETX};
#define TRUE 1
#define FALSE 0
extern unsigned char *g_get_1670buf;
int g_get_cmd_len;
int info_from_1670_len;
//extern int g_get_cmd_len;
//extern int info_from_1670_len;
void SetLoaderType(int dwLoaderType)
{
	SM_Printf("SetLoaderType() - SetLoaderType enter\r\n");
	s_dwLoaderType = dwLoaderType;
}


int DownloadDataInit(char* filename)
{
	return OpenSdlFile(filename);
}

int RemoveDownloadData(void)
{
	return CloseSdlFile();
}

void GetDownloadErrorInfo(unsigned long dwErrorCode, char **pErrorName, char **pbDescription)
{
	GetErrorinformation(s_dwLoaderType, dwErrorCode, pErrorName, pbDescription);
}

unsigned long GetDownloadData(char* pBuf, unsigned long dwOffset, unsigned long dwLength)
{
	unsigned long ret;

//	if (s_dwLoaderType == IRDETO_LOADER && s_dwDeviceId == PCMCIA_SLOT_DEVICE)
//	{
//		SM_Printf("GetDownloadData() SetLoaderType =%d\r\n",s_dwLoaderType);
//		pBuf[0] = 0x00;
//		pBuf[1] = 0x00;
//		ret = FileDataRead(pBuf + 2, dwOffset, dwLength);
//		ret+=2;
//	}
//	else 
		ret = FileDataRead(pBuf, dwOffset, dwLength);

	return ret;
}

void ShowDownloadSchedule(char bRate)
{
	static char s_bRate = 0;

	if (bRate != s_bRate)
	{
		s_bRate = bRate;
		if (s_dwDeviceId == PCMCIA_SLOT_DEVICE || s_dwDeviceId == USB_DONGLE_DEVICE || s_dwDeviceId == USB_CAM_DEVICE)
		{
			if(s_bRate == 100)
				SM_Printf("ShowDownloadSchedule() - ShowDownloadSchedule s_bRate = 100\r\n");
		}
		if (s_bRate == 100)
				SM_Printf("ShowDownloadSchedule() - ShowDownloadSchedule s_bRate = 100\r\n");
		else if (s_bRate >100 )
			s_bRate%=100;
	}
}

unsigned long GetDownloadDataLength(void)
{
	return GetFileLength();
}

int SsuDownloadFileInit(void)
{
	DelDLDII();
	return FileStructInit();
}

int SsuGetDii(unsigned char *pbDii, unsigned long *dwpdiiSize)
{
	unsigned long ret;
	unsigned long dwDiiOffset;
	unsigned short wDiiSize;

	ret = GetDiiDataInfo(&dwDiiOffset, &wDiiSize);
	if (ret == 0)
	{
		ret = GetDownloadData((char*)pbDii, dwDiiOffset, wDiiSize);
		*dwpdiiSize = wDiiSize;
		if (ret == wDiiSize)
			ret = 0;
	}
	return ret;
}

int SsuGetDdb(unsigned char *pbDdb, unsigned long *dwpDdbSize, unsigned short wModuleId, unsigned short wBlockNumber)
{
	unsigned long ret;
	unsigned long dwddbOffset;
	unsigned short wDdbSize;
	
	ret = GetDdbDataInfo(wModuleId, wBlockNumber, &dwddbOffset, &wDdbSize);
	if (ret == 0)
	{
		ret = GetDownloadData((char*)pbDdb, dwddbOffset, wDdbSize);
		*dwpDdbSize = wDdbSize;
		SM_Printf("SsuGetDdb() - entry ,wDdbSize = %d\r\n",wDdbSize);
		if (ret == wDdbSize)
			ret = 0;
	}
	return ret;
}

static unsigned long ModuleRead(unsigned char* data, unsigned long dwLen)
{
	unsigned long wSize;
	dwLen = g_get_cmd_len;
	memcpy(data, g_get_1670buf, g_get_cmd_len);
	wSize = g_get_cmd_len;
	SM_Printf("ModuleRead() - USB_Update_Read==================>\r\n");
#ifdef DEBUG_LXJ
	int i;
	for(i = 0; i <g_get_cmd_len;i ++)
	{
		SM_Printf("ModuleRead() - entry ,%02x \r\n", *(data + i ));
		if(0 == (i + 1)%6)
			SM_Printf("\t");
		if(0 == (i + 1)%24)
			SM_Printf("\r\n");
	}
#endif
	if(g_get_1670buf == NULL)
	{
		SM_Printf("ModuleRead() - g_get_1670buf is NULL \r\n");
	}
	if(g_get_1670buf)
	{
		free(g_get_1670buf);
	}
	
	g_get_cmd_len = 0;
	return wSize;
}

static unsigned long ModuleReadCommandData(unsigned char*pbcommand, unsigned long dwBufferSize, BOOL bFirstRead)
{
	int ret;
	unsigned short dwSize;
	unsigned char ch;
	unsigned long i;
	BOOL bIsValidCom = FALSE;
	
	while (!bIsValidCom)
	{
		SM_Printf("ModuleReadCommandData() - Sas_Update_Read before\n ");
		dwSize = Sas_Update_Read(pbcommand, dwBufferSize, &dwSize); //Sas_Update_Read(pbcommand, dwBufferSize);
		if (dwSize != 0)
			SM_Printf("ModuleReadCommandData() - pbcommand %x ", pbcommand[0]);
		if (dwSize == 0){
			SM_Printf("ModuleReadCommandData() - Sas_Update_Read no data read \n");
			continue;
		}

		if (!bFirstRead)
			break;

		for(i=0; i<dwSize; i++)
		{
			SM_Printf("ModuleReadCommandData() - entry , pbcommand %x ", pbcommand[i]);
			bIsValidCom = (pbcommand[i] == SOH || pbcommand[i] == STX);
			if (bIsValidCom) 
				break;
		}
		ch = pbcommand[i];
		pbcommand[i] = 0x00;
		SM_Printf("ModuleReadCommandData() - SnbIsValidCom value is %d \r\n",bIsValidCom);
		if (bIsValidCom) 
		{
			dwSize-=i;
			pbcommand[0] = ch;
			memmove(&pbcommand[1], &pbcommand[i + 1], dwSize - 1);
			break;
		}
	}

	return dwSize;
}

void ModuleWatchOneLine(void)
{
	unsigned long dwSize;
	unsigned char abBuf[1024] = {0};
	unsigned char abCh[2] = {0};

	while (1)
	{
		dwSize = ModuleRead(abBuf, 1024);
		if (dwSize == 0)
			continue;

		abBuf[dwSize] = 0;
		break;
	}
}

unsigned long IrdetoGetCommandSize(unsigned char bCommand)
{
	unsigned long dwSize = 0;

	switch (bCommand)
	{
	case CMD_STB_START:
	case CMD_STB_TIME_REQUEST:
	case CMD_FILE_SIZE:
	case CMD_REOPTION_LENGTH:
	case CMD_DATA_TRANSFER_END:
	case CMD_STB_DL_OK:
		dwSize = 3;
		break;
	case CMD_STB_ERROR:
		dwSize = 4;
		break;
	case CMD_STB_DATA_REQUEST:
		dwSize = 9;
		break;
	case CMD_MIXTERM_VER:
		dwSize = 8;
		break;
	case CMD_MANUFACTURER_TYPE_HWVER:
		dwSize = 15;
		break;
	case CMD_DATA_ERROR:
		dwSize = 7;
		break;
	default:
		break;
	}
	return dwSize;
}

int ModuleReadCommand(unsigned char* pbcommand, unsigned long dwBufferSize, unsigned long *dwCommandSize)
{
	unsigned long dwReadLength =0;
	unsigned long dwVaildCommandSize = 0;
	unsigned long i;
	BOOL bFirstRead = TRUE;
	
	while (1)
	{
		SM_Printf("ModuleReadCommand() -  Read the CMD !!!!!\r\n");
		dwReadLength += ModuleReadCommandData(pbcommand + dwReadLength, dwBufferSize, bFirstRead);
		bFirstRead = FALSE;
		if (pbcommand[0] == STX)
		{	
			
			if (dwReadLength < 2)
				continue;

			dwVaildCommandSize = IrdetoGetCommandSize(pbcommand[1]);
			if (dwReadLength < dwVaildCommandSize)
				continue;

			if (dwReadLength >= dwVaildCommandSize && pbcommand[dwVaildCommandSize -1] == ETX)
			{
				if (pbcommand[1] == CMD_STB_START)
					ModuleWriteCommand(s_abMixtermStart, 4);
				*dwCommandSize = dwVaildCommandSize;
				return 0;
			}
		}
		else if (pbcommand[0] == SOH)
		{
			if (dwReadLength < 6)
				continue;

			if ( pbcommand[1] == STX)
			{
				dwVaildCommandSize = ASN_READ_UINT32(&pbcommand[2]) + 8;
				if (dwReadLength < dwVaildCommandSize)
					continue;

				if (pbcommand[dwVaildCommandSize - 2] == ETX)
				{
					*dwCommandSize = dwVaildCommandSize;
					return 0;
				}
			}
		}
		
		for (i=1; i< dwReadLength; i++)
		{
			if (pbcommand[i]==SOH || pbcommand[i]== STX)
			{
				memmove(pbcommand, pbcommand+i, dwReadLength - i);
				dwReadLength-=i;
				dwVaildCommandSize = 0;
				break;
			}
		}
		if (dwReadLength == 0)
			bFirstRead = TRUE;
	}
	
	return -1;
}
/*
	function:Usb_Update_send
	for:用于1670升级专属接口
*/
/*static void Usb_Update_send(char *read_buf, int len)
{
	SM_Printf("\r\n[Update_Dbg]:<===========================USB_Update_send :\r\n");
#ifdef DEBUG_LXJ
	int i= 0;
	for(i = 0; i < len; i++)
	{
		SM_Printf("%02x ", *(read_buf + i));
		if(0 == (i+1)%6)
			SM_Printf("\t");
		if(0 == (i+1)%24)
			SM_Printf("\r\n");
	}
	SM_Printf("\r\n");
#endif
	unsigned char *send_buffer ;
	send_buffer = (unsigned char *)malloc(len + 3);
	/*这里使用的是TS的命令通道，因为USB在这里只针对TS
	的传输实现了一个通道，并没有针对升级设计一个通道
	所以这里就使用TS的命令通道，所以需要在头加上TS通道的头
	memset(send_buffer,0, len + 3);
	*(send_buffer+0) = MCU_CMD_TAG;
	*(send_buffer+1) = MCU_TS_CMD;
	*(send_buffer+2) = 0x04;
	memcpy(send_buffer+3, read_buf, len);
	Mcu_Usb_Send(send_buffer,len+3);
	if (send_buffer)
		free(send_buffer);
	
}*/
/*
*/

int Sas_Update_Send(const unsigned char *send_buf, unsigned short len)
{
	int ret = 0;
	ret = cisas_send_upgrade_data(send_buf, len);
	return ret;
}

int Sas_PrintLog_Send(const unsigned char *send_buf, unsigned short len) //add by yjzou
{
	int ret = 0;
	SM_Printf("Sas_PrintLog_Send() -  entry , Sas_PrintLog_Send begin send_buf=%s  len=%d\r\n",send_buf,len);
	ret = cisas_send_printlog_data(send_buf, len);
	SM_Printf("Sas_PrintLog_Send() -  return , ret = %d\r\n",ret);
	return ret;
}

int Sas_Update_Read(unsigned char *read_buf, unsigned long buf_size, unsigned short *len)
{
	
	cisas_get_upgrade_status(read_buf, len);
	SM_Printf("Sas_Update_Read() -  entry , read_buf = %x\r\n",read_buf[0]);
	SM_Printf("Sas_Update_Read() -  entry , read_buf = %x\r\n",read_buf[1]);
	SM_Printf("Sas_Update_Read() -  entry , read_buf = %x\r\n",read_buf[2]);
	SM_Printf("Sas_Update_Read() -  entry , read_buf = %x\r\n",read_buf[3]);
//	wTag = ASN_READ_UINT16(&pbCommand[0]);
	if(*len > buf_size){
		SM_Printf("Sas_Update_Read() -  return ,read buffer overflow\n");
		return -1;
	}
	return 0;
}

int ModuleWriteCommand(const unsigned char* pbcommand, unsigned short dwCommandSize)
{
	//SM_Printf("SasSend %x\n", pbcommand);
	int ret = -1;
	while(ret != 0){

		ret = Sas_Update_Send(pbcommand, dwCommandSize);
		if (ret != 0)
			sleep(1);
		SM_Printf("ModuleWriteCommand() -  return ,  ret = %d\r\n",ret);

	}
	return dwCommandSize;
}


